/**
 * $Id: GZSGIP851SubmitConnector.java,v 1.4 2007/02/08 08:21:14 martin Exp $
 *
 * Copyright 2005 Skyinfo, Inc. All Rights Reserved.
 */
package com.haoxi.gateway.connector.gzunicom;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.EOFException;
import java.io.IOException;
import java.net.Socket;
import java.net.SocketException;
import java.net.UnknownHostException;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.haoxi.gateway.common.CommonMsgBean;
import com.haoxi.gateway.connector.Connector;
import com.haoxi.gateway.runner.RunnerMgr;
import com.haoxi.gateway.sgip12msg.SGIPActiveMessage;
import com.haoxi.gateway.sgip12msg.SGIPActiveRepMessage;
import com.haoxi.gateway.sgip12msg.SGIPBindMessage;
import com.haoxi.gateway.sgip12msg.SGIPBindRepMessage;
import com.haoxi.gateway.sgip12msg.SGIPCommon;
import com.haoxi.gateway.sgip12msg.SGIPMessage;
import com.haoxi.gateway.sgip12msg.SGIPSubmitRepMessage;
import com.haoxi.gateway.sgip12msg.SGIPUnbindMessage;
import com.haoxi.gateway.sgip12msg.SGIPUnbindRepMessage;
import com.haoxi.gateway.sgip12msg.SequenceSower;

public class GZSGIP851SubmitConnector extends Connector {
    private static final Log log = LogFactory
            .getLog(GZSGIP851SubmitConnector.class);

    public GZSGIP851SubmitConnector(String aGatewayName, String connName,
            String aICP_ID, String loginName, String aPassword,
            String aGatewayIP, int aGatewayPort, int sVersion,
            String protcolName) {
        super(aGatewayName, connName, aICP_ID, loginName, aPassword,
                aGatewayIP, aGatewayPort, sVersion, protcolName);
    }

    public boolean checkConnect(String loginName, String password) {
        return true;
    }

    public CommonMsgBean readProtcol() throws IOException {
        CommonMsgBean result = null;
        int commid = 0;
        int readLength = 0;
        byte[] bodybytes = new byte[0];
        SGIPMessage respMessage = null;
        SGIPMessage reqMessage = null;
        try {
            if (soc != null && isSocketKeepLive && soc.isBound()
                    && soc.isConnected() && (!soc.isInputShutdown())
                    && (!soc.isOutputShutdown())) {
                int ch1 = in.read();
                if (ch1 < 0) {
                    // 流读完了，结束连接
                    //disConnected();
                    return result;
                }
                int ch2 = in.read();
                int ch3 = in.read();
                int ch4 = in.read();
                readLength = ((ch1 << 24) + (ch2 << 16) + (ch3 << 8) + (ch4 << 0));
                commid = in.readInt();
                bodybytes = new byte[readLength - 8];
                in.readFully(bodybytes);
            } else {
                //结束连接
                disConnected();
                return result;
            }
            if (commid == SGIPCommon.SGIP_SUBMIT_RESP) {
                reqMessage = new SGIPSubmitRepMessage(bodybytes);
                log.debug(reqMessage);
                resetSendMTNoRespCount();
                result = new CommonMsgBean();
                String gatewayCode = RunnerMgr.getInstance().getGatewayInfo()
                        .getGatewayCode();
                result.setCommid(SGIPCommon.SGIP_SUBMIT_RESP);
                result.setGateWayCode(gatewayCode);
                result.setConnName(this.connName);
                result.setBody(bodybytes);
            } else if (commid == SGIPCommon.SGIP_ACTIVE_TEST_RESP) {
                reqMessage = new SGIPActiveRepMessage(bodybytes);
                log.debug(reqMessage);
            } else if (commid == SGIPCommon.SGIP_ACTIVE_TEST) {
                reqMessage = new SGIPActiveRepMessage(bodybytes);
                respMessage = new SGIPActiveMessage();
                respMessage.setSequenceId(reqMessage.getSequenceId());
                respMessage.setSrcNodeId(reqMessage.getSrcNodeId());
                respMessage.setTimeStamp(reqMessage.getTimeStamp());
                out.write(respMessage.getBytes());
                out.flush();
            } else if (commid == SGIPCommon.SGIP_BIND_RESP) {
                reqMessage = new SGIPBindRepMessage(bodybytes);
                log.debug(reqMessage);
            } else if (commid == SGIPCommon.SGIP_UNBIND_RESP) {
                reqMessage = new SGIPUnbindRepMessage(bodybytes);
                log.debug(reqMessage);
                disConnected();
            } else if (commid == SGIPCommon.SGIP_UNBIND) {
                reqMessage = new SGIPUnbindMessage(bodybytes);
                respMessage = new SGIPUnbindRepMessage();
                respMessage.setSequenceId(reqMessage.getSequenceId());
                respMessage.setSrcNodeId(reqMessage.getSrcNodeId());
                respMessage.setTimeStamp(reqMessage.getTimeStamp());
                out.write(respMessage.getBytes());
                out.flush();
                log.debug(respMessage);
                disConnected();
            }
            // 打印日志消息
            // if (null != reqMessage
            // && (commid != SGIPCommon.SGIP_ACTIVE_TEST_RESP || commid !=
            // SGIPCommon.SGIP_ACTIVE_TEST)) {
            // log.debug(this.connName + "<<<<" + reqMessage.toString());
            // }
            // if (null != respMessage
            // && (commid != SGIPCommon.SGIP_ACTIVE_TEST_RESP || commid !=
            // SGIPCommon.SGIP_ACTIVE_TEST)) {
            // log.debug(this.connName + "<<<<" + respMessage.toString());
            // }

        } catch (IOException ex) {
            if (ex instanceof EOFException) {
                log.info("read the end of the stream has been reached!");
                return null;
            }
            if (ex instanceof SocketException) {
                log.error("catch an SocketException", ex);
            } else {
                log.error("catch an IOException", ex);
            }
            if (!isReOpen) {
                reOpenConnect();
            }
        }
        return result;
    }

    public boolean writeProtcol(CommonMsgBean obj) throws IOException {

        // 当连接通道被打开并且绑定成功这个时候才能向对方发送消息
        boolean result = false;
        if (isSocketKeepLive) {
            try {
                // 这里一定会抛异常
                out.write(obj.getBody());
                out.flush();
                result = true;
            } catch (IOException ex) {
                // 立刻断掉
                disConnected();
                result = false;
            }
        } else {
            result = false;
        }
        return result;
    } // 这里是测试一下是否正常连接

    public boolean openConnect() {
        boolean result = false;
        // 打开连接之前先将原先的连接设置为NULL
        soc = null;
        out = null;
        in = null;
        // boolean result = false;
        try {
            // 同对方握手
            soc = new Socket(gatewayIP, gatewayPort);
            in = new DataInputStream(new BufferedInputStream(soc
                    .getInputStream()));
            this.out = new DataOutputStream(new BufferedOutputStream(soc
                    .getOutputStream()));
            // 构造BIND消息
            SGIPBindMessage bind = new SGIPBindMessage(1, loginName, password);
            SequenceSower.setUnicomSequence(bind);
            // 发送BIND消息
            out.write(bind.getBytes());
            out.flush();
            log.debug(bind);
            int readLength = in.readInt();
            int commid = in.readInt();
            byte[] readbytes = new byte[0];
            SGIPBindRepMessage bindRep = null;
            if (SGIPCommon.SGIP_BIND_RESP == commid) {
                readbytes = new byte[readLength - 8];
                in.readFully(readbytes);
                bindRep = new SGIPBindRepMessage(readbytes);
                log.debug(bindRep);
                // 返回BIND是否成功
                result = (bindRep.getResult() == 0);
            }
        } catch (UnknownHostException unEx) {
            log.error("catch an UnknownHostException", unEx);
        } catch (IOException ex) {
            log.error("catch an Exception", ex);
        }
        return result;
    }

    /**
     * dis connection
     */
    public synchronized void disConnected() {
        this.isSocketKeepLive = false;
        String gatewayhead = gatewayName + " " + protcolName + " ";
        // try {
        // SGIPUnbindMessage unBind = new SGIPUnbindMessage();
        // SequenceSower.setUnicomSequence(unBind);
        // if (soc != null && soc.isBound() && soc.isConnected()) {
        // out.write(unBind.getBytes());
        // out.flush();
        // }
        // } catch (Exception ex) {
        // log.error("send unbind message unsuccesslly!");
        // }
        try {

            if (this.in != null) {
                this.in.close();
            }
        } catch (Exception e) {
            log.error(gatewayhead + "has a exception at input close:", e);
        } finally {
            this.in = null;
        }
        try {
            if (this.out != null) {
                this.out.close();
            }
        } catch (Exception e) {
            log.error(gatewayhead + "has a exception at output close:", e);
        } finally {
            this.out = null;
        }
        try {
            if (this.soc != null) {
                this.soc.close();
            }
            log.debug(gatewayhead + " is closed!");
        } catch (Exception e) {
            log.error(gatewayhead + "has a exception at socket close:", e);
        } finally {
            this.soc = null;
        }
    }

    /**
     * 因为是断连接直接保持正常
     */
    public boolean isClose() {
        return false;
    }
}
